package com.example.layoutincompose

import android.util.Log
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.*
import androidx.compose.ui.unit.*
import com.google.android.material.chip.Chip
import kotlin.math.max

// 自定义 Layout
object CustomLayoutDemo {
}

@Composable
fun CustomLayoutDemo() {
    Row {
        Text(
            text = "我是栗子1",
            modifier = Modifier.firstBaselineToTop(40.dp),
            fontSize = 20.sp
        )

        Spacer(modifier = Modifier.width(20.dp))

        Text(
            text = "我是栗子2",
            modifier = Modifier.firstBaselineToTop(40.dp),
            fontSize = 15.sp
        )

        Spacer(modifier = Modifier.width(20.dp))

        Text(
            text = "我是栗子3",
            modifier = Modifier.firstBaselineToTop(40.dp),
            fontSize = 30.sp
        )
    }
}

fun Modifier.firstBaselineToTop(
    firstBaselineToTop: Dp
) = this.then(
    layout { measurable, constraints ->
        val placeable = measurable.measure(constraints)

        check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
        val firstBaseline = placeable[FirstBaseline]
        Log.d("TAG", "firstBaselineToTop: firstBaseline = " + firstBaseline)

        val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
        Log.d("TAG", "firstBaselineToTop: placeable.height = " + placeable.height)
        Log.d("TAG", "firstBaselineToTop: placeableY = " + placeableY)
        val height = placeable.height + placeableY
        layout(placeable.width, height) {
            placeable.placeRelative(0, placeableY)
        }
    }
)


@Composable
fun MyOwnColumnDemo() {
    MyOwnColumn(Modifier.padding(20.dp)) {
        Text("我是栗子1")
        Text("我是栗子2")
        Text("我是栗子3")
    }
}

@Composable
fun MyOwnColumn(
    modifier: Modifier = Modifier,
    // 此处可添加自定义的参数
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // 对 children 进行测量和放置
        val placeables = measurables.map { measurable ->
            // 测量每个 child 的尺寸
            measurable.measure(constraints)
        }
        var yPosition = 0  // 记录下一个元素竖直方向上的位置
        layout(constraints.maxWidth, constraints.maxHeight) {
            // 摆放 children
            placeables.forEach { placeable ->
                placeable.placeRelative(x = 0, yPosition)
                yPosition += placeable.height
            }
        }
    }
}


// 横向瀑布流自定义 layout
@Composable
fun StaggeredGrid(
    modifier: Modifier = Modifier,
    rows: Int = 3,  // 自定义的参数，控制展示的行数，默认为 3行
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content,
        measurePolicy = object: MeasurePolicy {
            override fun MeasureScope.measure(
                measurables: List<Measurable>,
                constraints: Constraints
            ): MeasureResult {
                // 用于记录每一横行的宽度信息
                val rowWidths = IntArray(rows) { 0 }
                // 用于记录每一横行的高度信息
                val rowHeights = IntArray(rows) { 0 }
                // 测量每个 child 尺寸，获得每个 child 的 Placeable 对象
                val placeables = measurables.mapIndexed { index, measurable ->
                    // 标准流程：测量每个 child 尺寸，获得 placeable
                    val placeable = measurable.measure(constraints)
                    // 根据序号给每个 child 分组，记录每一个横行的宽高信息
                    val row = index % rows
                    rowWidths[row] += placeable.width
                    rowHeights[row] = max(rowHeights[row], placeable.height)
                    placeable    // 这句别忘了，返回每个 child 的placeable
                }

                // 自定义 Layout 的宽度取所有行中宽度最大值
                val width = rowWidths.maxOrNull()
                    ?.coerceIn(constraints.minWidth.rangeTo(constraints.maxWidth))
                    ?: constraints.minWidth
                // 自定义 Layout 的高度当然为所有行高度之和
                val height = rowHeights.sumOf { it }
                    .coerceIn(constraints.minHeight.rangeTo(constraints.maxHeight))
                // 计算出每一行的元素在 Y轴 上的摆放位置
                val rowY = IntArray(rows) { 0 }
                for (i in 1 until rows) {
                    rowY[i] = rowY[i - 1] + rowHeights[i - 1]
                }

                // 设置 自定义 Layout 的宽高
                return layout(width, height) {
                    // 摆放每个 child
                    val rowX = IntArray(rows) { 0 }  // child 在 X 轴的位置
                    placeables.forEachIndexed { index, placeable ->
                        val row = index % rows
                        placeable.placeRelative(
                            rowX[row],
                            rowY[row]
                        )
                        rowX[row] += placeable.width
                    }
                }
            }

//            override fun IntrinsicMeasureScope.minIntrinsicHeight(
//                measurables: List<IntrinsicMeasurable>,
//                width: Int
//            ): Int {
//                // 用于记录每一横行的宽度信息
//                val rowWidths = IntArray(rows) { 0 }
//                // 用于记录每一横行的高度信息
//                val rowHeights = IntArray(rows) { 0 }
//                measurables.mapIndexed { index, measurable ->
//                    // 标准流程：测量每个 child 尺寸，获得 placeable
//                    val minHeight = measurable.minIntrinsicHeight(width)
//                    // 根据序号给每个 child 分组，记录每一个横行的宽高信息
//                    val row = index % rows
////                    rowWidths[row] += placeable.width
//                    rowHeights[row] = max(rowHeights[row], minHeight)
//                }
//                return rowHeights.sum()
//            }
        }
    )
}

@Composable
fun Chip(
    modifier: Modifier = Modifier, text: String
) {
    Card(
        modifier = modifier,
        border = BorderStroke(color = Color.Magenta, width = Dp.Hairline),
        shape = RoundedCornerShape(8.dp)
    ) {
        Row(
            modifier = Modifier.padding(start = 8.dp, top = 4.dp, end = 8.dp, bottom = 4.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Box(
                modifier = Modifier
                    .size(16.dp, 16.dp)
                    .background(color = MaterialTheme.colors.secondary)
            )
            Spacer(Modifier.width(4.dp))
            Text(text = text)
        }
    }
}


// Modifier.layout 的另一种写法
fun Modifier.firstBaselineToTop2(
    firstBaselineToTop: Dp
) {
    Modifier.layout { measurable, constraints ->
        val placeable = measurable.measure(constraints)

        check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
        val firstBaseline = placeable[FirstBaseline]
        Log.d("TAG", "firstBaselineToTop: firstBaseline = " + firstBaseline)

        val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
        Log.d("TAG", "firstBaselineToTop: placeable.height = " + placeable.height)
        Log.d("TAG", "firstBaselineToTop: placeableY = " + placeableY)
        val height = placeable.height + placeableY
        layout(placeable.width, height) {
            placeable.placeRelative(0, placeableY)
        }
    }
}




